#!/usr/bin/php
<?php
/**
 * <https://y.st./>
 * Copyright © 2015-2019 Alex Yst <mailto:copyright@y.st>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org./licenses/>.
**/

/**
 * This source code requires PHP to compile. It was tested with PHP
 * 5.6.6-2, but will likely work with anything at least as recent as
 * PHP 5.3. Any PHP version older than that lacks name spaces, and will
 * not work with this code. To install PHP without installing a Web
 * server, install the "php5-cli" on Debian. The package may be under a
 * different name on other systems and distributions. Additionally, you
 * will need PECL's gnupg_*() functions and the DOM extension.
 * 
 * sudo aptitude install php7-cli php7-gnupg php7-dom
 * 
 * You will need to install the include.d PHP library, which is not
 * available from the Debian repository. It can be found at
 * <https://notabug.org./y.st./include.d>.
**/

// Used for end-of-run statistics output
$time_script_started = time();

// A little setup ...
spl_autoload_register();
require 'st/y/function/error_handler.php';
require 'st/y/function/highlight_string.php';
require 'st/y/function/recurse_dir.php';
require 'st/y/function/update_file.php';
require 'st/y/function/xml_is_clean.php';
set_error_handler('\\st\\y\\error_handler');
require __DIR__.'/source/variables.php';
require __DIR__.'/source/closure.php';

// Load the previously-saved state value:
$saved_state = unserialize(file_get_contents(__DIR__.'/source/saved state.txt'));

// If invalid arguments are used, the whole compilation process should
// halt and an error message should be presented.
if(isset($invalid_arguments)):
	die("\nInvalid arguments: ".implode(' ', $invalid_arguments)."\n\n");
endif;

// If the canary chirps ...
if(in_array('--canary', $argv)):
	ob_start();
	require __DIR__.'/source/canary.php';
	$canary = $pgp->sign(ob_get_clean());
	\st\y\update_file(__DIR__.'/static/a/canary.txt', $canary);
	$saved_state['days_until_freedom_as_of_last_canary_chirp'] = $days_until_freedom;
	$saved_state['days_until_freedom_as_of_last_canary_chirp_extended'] = $days_until_freedom + 365;
else:
	echo "\nYou did not run this script using the \"--canary\" flag. Is everything okay?\n\n";
endif;

// If there's new course data, parse it and replace the old data.
// Then remove the useless, unparsed data.
if(file_exists(__DIR__.'/source/input/courses.txt')):
	$input = explode("\n", file_get_contents(__DIR__.'/source/input/courses.txt'));
	$new_courses = array();
	for($i=0; isset($input[$i]); $i+=3):
		$key = explode("\t", $input[$i+1])[1];
		$key = str_replace(' ', '', $key);
		$new_courses[$key] = $input[$i];
		if(empty($saved_state['courses'][$key])):
			$saved_state['courses'][$key] = $input[$i];
		endif;
	endfor;
	ksort($saved_state['courses']);
	$courses_lost = false;
	foreach($saved_state['courses'] as $key => $value):
		if(empty($new_courses[$key])):
			echo "$key removed from the list of available courses!!\n";
			$courses_lost = true;
		endif;
	endforeach;
	if($courses_lost):
		echo "\nSome courses seem to have been removed!\nUpdate the course schedule!\n\n";
	else:
		unlink(__DIR__.'/source/input/courses.txt');
	endif;
endif;

// A loading bar to track my remaining time at this wretched school:
$temp = 0;
foreach($coursework as $key => $value):
	if(empty($value['assignments']['Unit_7_essay'])):
		++$temp;
	endif;
endforeach;
echo "Schooling completed:\n";
echo str_repeat('#', $temp), '--', str_repeat('_', max(0, 44 - $temp - 2));
echo "\n| YEAR 0 || YEAR 1 || YEAR 2 || YEAR 3 ||??|\n\n";

/*
$needed_courses = array(
	'CS3304'   => true,
	'CS3306'   => true,
	'CS3307'   => true,
	'CS3308'   => true,
	'CS4403'   => true,
	'CS4404'   => true,
	'CS4405'   => true,
	'CS4406'   => true,
	'CS4408'   => true,
	'MATH1211' => true,
	'MATH1302' => true,
);
$needed_course_list = '';
$elective_course_list = '';

foreach($saved_state['courses'] as $key => $value):
	if(isset($coursework[$key])):
		echo "\t\t<a href=\"/en/coursework/$key/\" title=\"$value\">$key</a> |\n";
	else:
		echo "\t\t<span class=\"hyperlink_unavailable\" title=\"$value\">$key</span> |\n";
	endif;
	if(!isset($coursework[$key])):
		if(isset($needed_courses[$key])):
			$needed_course_list .= "=> $key: $value\n";
		else:
			$elective_course_list .= "-> $key: $value\n";
		endif;
	endif;
endforeach;

echo "Remaining courses:\n", $needed_course_list, $elective_course_list, "\n";
*/

// Tell PHP to use detached signatures, so the XHTML pages will still validate.
$pgp->setsignmode(GNUPG_SIG_MODE_DETACH);

// Some files are static, and only need to be copied, not compiled.
foreach(\st\y\recurse_dir(__DIR__.'/static') as $filename):
// TO DO: This conditional is hacky; fix it. Check path prefixes
// against keys or values in an array or something.
	if(substr($filename, 0, 34) != 'img/CC_BY-SA_4.0/y.st./coursework/'):
		$dirname = dirname(__DIR__."/compiled/$filename");
		if(!is_dir($dirname)):
			mkdir($dirname, 0777, true);
		endif;
		\st\y\update_file(__DIR__."/compiled/$filename", file_get_contents(__DIR__."/static/$filename"));
		$should_exist[$filename] = true;
	endif;
endforeach;

// Other files are compiled.
foreach(\st\y\recurse_dir(__DIR__."/source/pages") as $filename):
	require __DIR__."/source/pages/$filename";
// Some pages have been censored by third parties.
	if(isset($xhtml['takedown'])):
		require __DIR__."/source/pages/en/take-down/$xhtml[takedown].xhtml";
		$censored_pages++;
	endif;
	$¢_build_page($filename, $xhtml);
endforeach;

// Account for moved pages.
require __DIR__.'/source/redirect.php';

// Directory indexes should be built.
require __DIR__.'/source/weblog_index.php';

// Copy the English index to the main index because the plan to set up
// an Esperanto version of the website sort of flopped.
//copy(__DIR__.'/compiled/en/index.xhtml', __DIR__.'/compiled/index.xhtml');
//$should_exist['index.xhtml'] = true;

// The current host doesn't handle index files with a ".xhtml"
// extension, but it does serve Content-Type headers base on the
// content of the file instead of the file extension. The index files
// will therefore be served as XHTML even with the wrong file
// extension. To get them to also be treated as index files, let's copy
// all "index.xhtml" files to "index.html".
// 
// Actually, never mind. That host's administrator got frustrated that
// I didn't want to use the host name or TLS certificate "authority"
// they like, and decided to stop helping me with unrelated issues
// regarding their server, such as that the server does use file
// extensions after all to decided on Content-Type headers to send and
// that "index.xhtml" isn't recognised as an index file name by the
// server. That hosting isn't going to work out, so there's no reason
// to copy the index files to a new location. Comment this out until a
// day it might one day be needed again.
#foreach(\st\y\recurse_dir(__DIR__.'/compiled') as $filename):
#	if(substr($filename, -11) == 'index.xhtml'):
#		$temp_filename = substr($filename, 0, -5).'html';
#		$should_exist[$temp_filename] = true;
#		$temp_file = file_get_contents(__DIR__.'/compiled/'.$filename);
#		if(!file_exists(__DIR__.'/compiled/'.$temp_filename) or
#		$temp_file != file_get_contents(__DIR__.'/compiled/'.$temp_filename)):
#			file_put_contents(__DIR__.'/compiled/'.$temp_filename, $temp_file);
#		endif;
#	endif;
#endforeach;

foreach(\st\y\recurse_dir(__DIR__.'/compiled') as $filename):
	if(!isset($should_exist[$filename]) and substr($filename, 0, 5) != '.git/'):
		unlink(__DIR__."/compiled/$filename");
	endif;
endforeach;

// Save the state of some values for next time:
$saved_state['censored_pages'] = $censored_pages;
file_put_contents(__DIR__.'/source/saved state.txt', serialize($saved_state));

// End-of-run statistics:
$time_until_script_ended = time() - $time_script_started;
echo <<<END
The script completed in $time_until_script_ended seconds.
$censored_pages pages have been censored.

END;
